package com.beyondsoft.mcms.web;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import org.apache.commons.io.IOUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.roo.addon.web.mvc.controller.finder.RooWebFinder;
import org.springframework.roo.addon.web.mvc.controller.scaffold.RooWebScaffold;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.ServletRequestDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.support.ByteArrayMultipartFileEditor;
import com.beyondsoft.mcms.common.CommonUtils;
import com.beyondsoft.mcms.domain.Conference;
import com.beyondsoft.mcms.domain.Document;
import com.beyondsoft.mcms.reference.AuthRole;

@RequestMapping("/documents")
@Controller
@RooWebScaffold(path = "documents", formBackingObject = Document.class, update = false)
@RooWebFinder
public class DocumentController {

    private static final Log log = LogFactory.getLog(DocumentController.class);

    @InitBinder
    protected void initBinder(HttpServletRequest request, ServletRequestDataBinder binder) throws ServletException {
        // Convert multipart object to byte[]
        binder.registerCustomEditor(byte[].class, new ByteArrayMultipartFileEditor());
    }

    void populateEditForm(Model uiModel, Document document) {
        uiModel.addAttribute("document", document);
        addDateTimeFormatPatterns(uiModel);
        List<Conference> conferences = Conference.findAllConferences();
        Conference noConference = new Conference();
        noConference.setId(-1L);
        noConference.setName("－－");
        conferences.add(0, noConference);
        uiModel.addAttribute("conferences", conferences);
    }

    @RequestMapping(params = "form", produces = "text/html")
    public String createForm(Model uiModel) {
        Document document = new Document();
        document.setCreateDate(new Date());
        document.setCreatedBy(CommonUtils.getCurrentUsername());
        populateEditForm(uiModel, document);
        return "documents/create";
    }

    @RequestMapping(value = "savedoc", method = RequestMethod.POST)
    public String createdoc(@Valid Document document, BindingResult result, Model model, @RequestParam("content") MultipartFile content, HttpServletRequest request) {
        if (result.hasErrors()) {
            model.addAttribute("document", document);
            return "documents/create";
        }
      
         if (content.getSize() > 1024 * 1024 * 20) {
	         model.addAttribute("document", document);
	         result.rejectValue("content", "document_size_g_10m");
	         document.setContent(null);
	         populateEditForm(model, document);
	         return "documents/create";
         }
        
        document.setContentType(content.getContentType());
        document.setFileName(content.getOriginalFilename());
        document.setFileSize(content.getSize());
        log.debug("Document: ");
        log.debug("Name: " + content.getOriginalFilename());
        log.debug("Description: " + document.getDescription());
        log.debug("File: " + content.getName());
        log.debug("Type: " + content.getContentType());
        log.debug("Size: " + content.getSize());
        if (document.getConference() == null || document.getConference().getId().equals(-1L)) {
            document.setConference(null);
        }
        documentService.saveDocument(document);
        return "redirect:/documents/" + encodeUrlPathSegment(document.getId().toString(), request);
    }

    @RequestMapping(value = "/{id}", method = RequestMethod.GET)
    public String show(@PathVariable("id") Long id, Model model, HttpServletRequest request) throws Exception {
        Document doc = Document.findDocument(id);
        String contextPath = request.getContextPath();
        doc.setUrl(CommonUtils.getRequestAddr(request) + contextPath + "/documents/showdoc/" + id);
        model.addAttribute("document", Document.findDocument(id));
        model.addAttribute("itemId", id);
        AuthRole authority = CommonUtils.getCurrentRole();
        if (authority.equals(AuthRole.ORDINARY)) {
            return "documents/ordinaryshow";
        }
        return "documents/show";
    }

    @RequestMapping(value = "showdoc/{id}", method = RequestMethod.GET)
    public String showdoc(@PathVariable("id") Long id, HttpServletRequest request, HttpServletResponse response, Model model) {
        Document doc = Document.findDocument(id);
        try {
            response.setHeader("Content-Disposition", "attachment;filename=\"" + encodeUrlPathSegment(doc.getFileName(), request) + "\"");
            OutputStream out = response.getOutputStream();
            response.setContentType(doc.getContentType());
            IOUtils.copy(new ByteArrayInputStream(doc.getContent()), out);
            out.flush();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /*
     * @RequestMapping(value = "/{id}", params = "form", method =
     * RequestMethod.GET) public String updateForm(@PathVariable("id") Long id,
     * Model model) { Document document = Document.findDocument(id);
     * document.setUrl("http://localhost:8080/mcms/documents/showdoc/" + id);
     * model.addAttribute("document", document); return "documents/update"; }
     */
    @RequestMapping(params = { "find=ByConference", "form" }, method = RequestMethod.GET)
    public String findDocumentsByConferenceForm(Model uiModel) {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        request.getSession().setAttribute("conference", null);
        return findDocumentsByConference(null, uiModel);
    }

    @RequestMapping(params = "find=ByConference", method = RequestMethod.GET)
    public String findDocumentsByConference(@RequestParam(value = "conference", required = false) Conference conference, Model uiModel) {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String page = request.getParameter("page");
        String size = request.getParameter("size");
        int sizeNo = size == null ? 10 : Integer.valueOf(size);
        int pageNo = page == null ? 1 : Integer.valueOf(page);
        if (page != null && size != null) {
            conference = (Conference) request.getSession().getAttribute("conference");
        } else {
            request.getSession().setAttribute("Conference", conference);
        }
        uiModel.addAttribute("conference", conference);
        return list(pageNo, sizeNo, uiModel);
    }

    @RequestMapping(produces = "text/html")
    public String list(@RequestParam(value = "page", required = false) Integer page, @RequestParam(value = "size", required = false) Integer size, Model uiModel) {
        int sizeNo = size == null ? 10 : size.intValue();
        final int firstResult = page == null ? 0 : (page.intValue() - 1) * sizeNo;
        float nrOfPages = 0.0f;
        Conference conference = (Conference) uiModel.asMap().get("conference");
        List<Document> documents = Document.findDocumentsByConference(conference).getResultList();
        int lastResult = (documents.size() > (sizeNo + firstResult)) ? (sizeNo + firstResult) : documents.size();
        uiModel.addAttribute("documents", documents.subList(firstResult, lastResult));
        nrOfPages = (float) documents.size() / sizeNo;
        if (CommonUtils.getCurrentRole().equals(AuthRole.ADMIN)) {
            uiModel.addAttribute("conferences", Conference.findAllConferences());
        } else {
            uiModel.addAttribute("conferences", Conference.findAllConferences());
        }
        uiModel.addAttribute("maxPages", (int) ((nrOfPages > (int) nrOfPages || nrOfPages == 0.0) ? nrOfPages + 1 : nrOfPages));
        uiModel.addAttribute("find", "ByConference"); // differ non-query
        // request
        uiModel.addAttribute("selectQueryIds", (conference == null ? -1 : conference.getId()));
        AuthRole authority = CommonUtils.getCurrentRole();
        if (authority.equals(AuthRole.ORDINARY)) {
            return "documents/ordinarylist";
        }
        return "documents/list";
    }

    @RequestMapping(value = "list/{id}", produces = "text/html")
    public String listByConference(@PathVariable("id") Long id, Model uiModel) {
        uiModel.addAttribute("conference", Conference.findConference(id));
        return list(1, 10, uiModel);
    }
}
